﻿using Core.DataAccess.Model;
using Core.Framework;
using Dapper;
using Grain.Interfaces;
using Grain.State.StateEntitys;
using iTool.ClusterComponent;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Grain.Implements
{
    public class EditCloudFunctionService : iToolServiceStorageProducerBase<EditCloudFunctionState>, IEditCloudFunctionService
    {
        private IDBFactory iDBFactory;

        public EditCloudFunctionService(IDBFactory iDBFactory) : base(AppSetting.QueueServiceStreamNamespace)
        {
            this.iDBFactory = iDBFactory;
        }

        public async Task Edit(string script, string channel)
        {

            if (this.State.scriptContent == script)
            {
                return;
            }

            if (this.State.EditChannel != channel)
            {
                // 写入渠道
                this.State.EditChannel = channel;

                // 获取渠道Service
                IChannelService channelService = this.GrainFactory.GetGrain<IChannelService>(channel);
                // 获取渠道信息
                var channelParameter = (await channelService.GetChannelInfo()).TryToJObject();
                channelParameter.TryGetValue("name", out JToken value);
                this.State.EditChannelName = value.ToString();

                // 设置编辑状态
                this.State.IsEditState = true;

                // 获取列表的Service
                IEditCloudFunctionListService editCloudFunctionList = this.GetService<IEditCloudFunctionListService>();
                // 设置列表的编辑状态
                await editCloudFunctionList.EnterEditState(this.State.moduleName, this.State.EditChannelName);

            }

            // 通知客户端
            await this.SendMessageAsync(AppSetting.ScriptEditTopic, JsonConvert.SerializeObject(new
            {
                Topic = "edit_functions",
                Body = new
                {
                    action = "fileContent",
                    parameter = new
                    {
                        modulePath = this.State.moduleName,
                        changeValue = script,
                        isBroadcast = true,
                        editUserName = this.State.EditChannelName
                    }
                }.TryToJson()
            }));

            this.State.scriptContent = script;

        }

        public async Task ExitEditState(string script)
        {
            this.State.EditChannelName = string.Empty;
            this.State.EditChannel = string.Empty;
            this.State.IsEditState = false;

            if (!string.IsNullOrWhiteSpace(script))
            {
                this.State.scriptContent = script;
            }

            // 获取列表的Service
            IEditCloudFunctionListService editCloudFunctionList = this.GetService<IEditCloudFunctionListService>();
            // 设置列表的编辑状态
            await editCloudFunctionList.ExitEditState(this.State.moduleName);

        }

        public Task<EditCloudFunctionState> GetDetail()
        {
            return Task.FromResult(this.State);
        }

        public async Task Modify(string script)
        {
            this.State.scriptContent = script;
            KeyValuePair<string, string> message = new KeyValuePair<string, string>("./CloudFunctions/" + this.State.moduleName, script);
            await this.SendMessageAsync(AppSetting.ScriptBudilerTopic, JsonConvert.SerializeObject(message));
            await this.WriteStateAsync();
        }

        public async Task Remove()
        {
            // 获取列表的Service
            IEditCloudFunctionListService editCloudFunctionList = this.GetService<IEditCloudFunctionListService>();
            // 从列表删除
            await editCloudFunctionList.RemoveFunction(this.State.moduleName);

            KeyValuePair<string, string> message = new KeyValuePair<string, string>(this.State.modulePath, string.Empty);
            await this.SendMessageAsync(AppSetting.ScriptDeleteTopic, JsonConvert.SerializeObject(message));
            await this.ClearStateAsync();
            base.PlanDispose();
        }

        protected override Task ClearStateAsync()
        {
            using (var db = this.iDBFactory.Create(DatabaseType.Function))
            {
                var result = db.Execute($"delete [Function] where id = {this.State.id}");
            }
            return Task.CompletedTask;
        }

        protected override Task ReadStateAsync()
        {
            string moduleName = this.GetStringKey();
            try
            {
                using (var db = this.iDBFactory.Create(DatabaseType.Function))
                {
                    this.State = db.QueryFirstOrDefault<EditCloudFunctionState>($"select id,moduleName,modulePath,scriptContent from [Function] where moduleName = @moduleName", new { moduleName }) 
                        ?? new EditCloudFunctionState 
                        {
                            moduleName = moduleName,
                            modulePath = $"./CloudFunctions/{moduleName}"
                        };
                }

                this.State.modulePath = this.State.modulePath + "_module";
            }
            catch (System.Exception ex)
            {
                System.Console.WriteLine("ReadStateAsync:{0},error:{1}", moduleName, ex);
            }

            return Task.CompletedTask;
        }

        protected override Task WriteStateAsync()
        {
            using (var db = this.iDBFactory.Create(DatabaseType.Function))
            {
                db.Execute($"update [Function] set scriptContent=@script where id = @id", new { id = this.State.id, script = this.State.scriptContent });
            }

            return Task.CompletedTask;
        }
    }

}
